home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Hexen Source / R_PLANE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-22  |  12.6 KB  |  560 lines

  1.  
  2. //**************************************************************************
  3. //**
  4. //** r_plane.c : Heretic 2 : Raven Software, Corp.
  5. //**
  6. //** $RCSfile: r_plane.c,v $
  7. //** $Revision: 1.5 $
  8. //** $Date: 95/07/13 15:17:12 $
  9. //** $Author: cjr $
  10. //**
  11. //**************************************************************************
  12.  
  13. // HEADER FILES ------------------------------------------------------------
  14.  
  15. #include "h2def.h"
  16. #include "r_local.h"
  17.  
  18. // MACROS ------------------------------------------------------------------
  19.  
  20. // TYPES -------------------------------------------------------------------
  21.  
  22. // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
  23.  
  24. // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
  25.  
  26. // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
  27.  
  28. // EXTERNAL DATA DECLARATIONS ----------------------------------------------
  29.  
  30. extern fixed_t Sky1ScrollDelta;
  31. extern fixed_t Sky2ScrollDelta;
  32.  
  33. // PUBLIC DATA DEFINITIONS -------------------------------------------------
  34.  
  35. int Sky1Texture;
  36. int Sky2Texture;
  37. fixed_t Sky1ColumnOffset;
  38. fixed_t Sky2ColumnOffset;
  39. int skyflatnum;
  40. int skytexturemid;
  41. fixed_t skyiscale;
  42. boolean DoubleSky;
  43. planefunction_t floorfunc, ceilingfunc;
  44.  
  45. // Opening
  46. visplane_t visplanes[MAXVISPLANES], *lastvisplane;
  47. visplane_t *floorplane, *ceilingplane;
  48. short openings[MAXOPENINGS], *lastopening;
  49.  
  50. // Clip values are the solid pixel bounding the range.
  51. // floorclip start out SCREENHEIGHT
  52. // ceilingclip starts out -1
  53. short floorclip[SCREENWIDTH];
  54. short ceilingclip[SCREENWIDTH];
  55.  
  56. // spanstart holds the start of a plane span, initialized to 0
  57. int spanstart[SCREENHEIGHT];
  58. int spanstop[SCREENHEIGHT];
  59.  
  60. // Texture mapping
  61. lighttable_t **planezlight;
  62. fixed_t planeheight;
  63. fixed_t yslope[SCREENHEIGHT];
  64. fixed_t distscale[SCREENWIDTH];
  65. fixed_t basexscale, baseyscale;
  66. fixed_t cachedheight[SCREENHEIGHT];
  67. fixed_t cacheddistance[SCREENHEIGHT];
  68. fixed_t cachedxstep[SCREENHEIGHT];
  69. fixed_t cachedystep[SCREENHEIGHT];
  70.  
  71. // PRIVATE DATA DEFINITIONS ------------------------------------------------
  72.  
  73. // CODE --------------------------------------------------------------------
  74.  
  75. //==========================================================================
  76. //
  77. // R_InitSky
  78. //
  79. // Called at level load.
  80. //
  81. //==========================================================================
  82.  
  83. void R_InitSky(int map)
  84. {
  85.     Sky1Texture = P_GetMapSky1Texture(map);
  86.     Sky2Texture = P_GetMapSky2Texture(map);
  87.     Sky1ScrollDelta = P_GetMapSky1ScrollDelta(map);
  88.     Sky2ScrollDelta = P_GetMapSky2ScrollDelta(map);
  89.     Sky1ColumnOffset = 0;
  90.     Sky2ColumnOffset = 0;
  91.     DoubleSky = P_GetMapDoubleSky(map);
  92. }
  93.  
  94. //==========================================================================
  95. //
  96. // R_InitSkyMap
  97. //
  98. // Called whenever the view size changes.
  99. //
  100. //==========================================================================
  101.  
  102. void R_InitSkyMap(void)
  103. {
  104.     skyflatnum = R_FlatNumForName("F_SKY");
  105.     skytexturemid = 200*FRACUNIT;
  106.     skyiscale = FRACUNIT;
  107. }
  108.  
  109. //==========================================================================
  110. //
  111. // R_InitPlanes
  112. //
  113. // Called at game startup.
  114. //
  115. //==========================================================================
  116.  
  117. void R_InitPlanes(void)
  118. {
  119. }
  120.  
  121. //==========================================================================
  122. //
  123. // R_MapPlane
  124. //
  125. // Globals used: planeheight, ds_source, basexscale, baseyscale,
  126. // viewx, viewy.
  127. //
  128. //==========================================================================
  129.  
  130. void R_MapPlane(int y, int x1, int x2)
  131. {
  132.     angle_t angle;
  133.     fixed_t distance, length;
  134.     unsigned index;
  135.  
  136. #ifdef RANGECHECK
  137.     if(x2 < x1 || x1 < 0 || x2 >= viewwidth || (unsigned)y > viewheight)
  138.     {
  139.         I_Error("R_MapPlane: %i, %i at %i", x1, x2, y);
  140.     }
  141. #endif
  142.  
  143.     if(planeheight != cachedheight[y])
  144.     {
  145.         cachedheight[y] = planeheight;
  146.         distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
  147.         ds_xstep = cachedxstep[y] = FixedMul(distance, basexscale);
  148.         ds_ystep = cachedystep[y] = FixedMul(distance, baseyscale);
  149.     }
  150.     else
  151.     {
  152.         distance = cacheddistance[y];
  153.         ds_xstep = cachedxstep[y];
  154.         ds_ystep = cachedystep[y];
  155.     }
  156.     
  157.     length = FixedMul(distance, distscale[x1]);
  158.     angle = (viewangle+xtoviewangle[x1])>>ANGLETOFINESHIFT;
  159.     ds_xfrac = viewx+FixedMul(finecosine[angle], length);
  160.     ds_yfrac = -viewy-FixedMul(finesine[angle], length);
  161.  
  162.     if(fixedcolormap)
  163.     {
  164.         ds_colormap = fixedcolormap;
  165.     }
  166.     else
  167.     {
  168.         index = distance >> LIGHTZSHIFT;
  169.         if(index >= MAXLIGHTZ )
  170.         {
  171.             index = MAXLIGHTZ-1;
  172.         }
  173.         ds_colormap = planezlight[index];
  174.     }
  175.  
  176.     ds_y = y;
  177.     ds_x1 = x1;
  178.     ds_x2 = x2;
  179.  
  180.     spanfunc(); // High or low detail
  181. }
  182.  
  183. //==========================================================================
  184. //
  185. // R_ClearPlanes
  186. //
  187. // Called at the beginning of each frame.
  188. //
  189. //==========================================================================
  190.  
  191. void R_ClearPlanes(void)
  192. {
  193.     int i;
  194.     angle_t angle;
  195.  
  196.     // Opening / clipping determination
  197.     for(i = 0; i < viewwidth; i++)
  198.     {
  199.         floorclip[i] = viewheight;
  200.         ceilingclip[i] = -1;
  201.     }
  202.  
  203.     lastvisplane = visplanes;
  204.     lastopening = openings;
  205.  
  206.     // Texture calculation
  207.     memset(cachedheight, 0, sizeof(cachedheight));    
  208.     angle = (viewangle-ANG90)>>ANGLETOFINESHIFT; // left to right mapping
  209.     // Scale will be unit scale at SCREENWIDTH/2 distance
  210.     basexscale = FixedDiv(finecosine[angle], centerxfrac);
  211.     baseyscale = -FixedDiv(finesine[angle], centerxfrac);
  212. }
  213.  
  214. //==========================================================================
  215. //
  216. // R_FindPlane
  217. //
  218. //==========================================================================
  219.  
  220. visplane_t *R_FindPlane(fixed_t height, int picnum,
  221.     int lightlevel, int special)
  222. {
  223.     visplane_t *check;
  224.  
  225.     if(special < 150)
  226.     { // Don't let low specials affect search
  227.         special = 0;
  228.     }
  229.  
  230.     if(picnum == skyflatnum)
  231.     { // All skies map together
  232.         height = 0;
  233.         lightlevel = 0;
  234.     }
  235.  
  236.     for(check = visplanes; check < lastvisplane; check++)
  237.     {
  238.         if(height == check->height
  239.         && picnum == check->picnum
  240.         && lightlevel == check->lightlevel
  241.         && special == check->special)
  242.             break;
  243.     }
  244.  
  245.     if(check < lastvisplane)
  246.     {
  247.         return(check);
  248.     }
  249.  
  250.     if(lastvisplane-visplanes == MAXVISPLANES)
  251.     {
  252.         I_Error("R_FindPlane: no more visplanes");
  253.     }
  254.  
  255.     lastvisplane++;
  256.     check->height = height;
  257.     check->picnum = picnum;
  258.     check->lightlevel = lightlevel;
  259.     check->special = special;
  260.     check->minx = SCREENWIDTH;
  261.     check->maxx = -1;
  262.     memset(check->top, 0xff, sizeof(check->top));
  263.     return(check);
  264. }
  265.  
  266. //==========================================================================
  267. //
  268. // R_CheckPlane
  269. //
  270. //==========================================================================
  271.  
  272. visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop)
  273. {
  274.     int intrl, intrh;
  275.     int unionl, unionh;
  276.     int x;
  277.  
  278.     if(start < pl->minx)
  279.     {
  280.         intrl = pl->minx;
  281.         unionl = start;
  282.     }
  283.     else
  284.     {
  285.         unionl = pl->minx;
  286.         intrl = start;
  287.     }
  288.     if(stop > pl->maxx)
  289.     {
  290.         intrh = pl->maxx;
  291.         unionh = stop;
  292.     }
  293.     else
  294.     {
  295.         unionh = pl->maxx;
  296.         intrh = stop;
  297.     }
  298.  
  299.     for(x = intrl; x <= intrh; x++)
  300.     {
  301.         if(pl->top[x] != 0xff)
  302.         {
  303.             break;
  304.         }
  305.     }
  306.  
  307.     if(x > intrh)
  308.     {
  309.         pl->minx = unionl;
  310.         pl->maxx = unionh;
  311.         return pl; // use the same visplane
  312.     }
  313.  
  314.     // Make a new visplane
  315.     lastvisplane->height = pl->height;
  316.     lastvisplane->picnum = pl->picnum;
  317.     lastvisplane->lightlevel = pl->lightlevel;
  318.     lastvisplane->special = pl->special;
  319.     pl = lastvisplane++;
  320.     pl->minx = start;
  321.     pl->maxx = stop;
  322.     memset(pl->top, 0xff, sizeof(pl->top));
  323.  
  324.     return pl;
  325. }
  326.  
  327. //==========================================================================
  328. //
  329. // R_MakeSpans
  330. //
  331. //==========================================================================
  332.  
  333. void R_MakeSpans(int x, int t1, int b1, int t2, int b2)
  334. {
  335.     while(t1 < t2 && t1 <= b1)
  336.     {
  337.         R_MapPlane(t1, spanstart[t1], x-1);
  338.         t1++;
  339.     }
  340.     while(b1 > b2 && b1 >= t1)
  341.     {
  342.         R_MapPlane(b1, spanstart[b1], x-1);
  343.         b1--;
  344.     }
  345.     while(t2 < t1 && t2 <= b2)
  346.     {
  347.         spanstart[t2] = x;
  348.         t2++;
  349.     }
  350.     while(b2 > b1 && b2 >= t2)
  351.     {
  352.         spanstart[b2] = x;
  353.         b2--;
  354.     }
  355. }
  356.  
  357. //==========================================================================
  358. //
  359. // R_DrawPlanes
  360. //
  361. //==========================================================================
  362.  
  363. #define SKYTEXTUREMIDSHIFTED 200
  364.  
  365. void R_DrawPlanes(void)
  366. {
  367.     visplane_t *pl;
  368.     int light;
  369.     int x, stop;
  370.     int angle;
  371.     byte *tempSource;
  372.     byte *source;
  373.     byte *source2;
  374.     byte *dest;
  375.     int count;
  376.     int offset;
  377.     int skyTexture;
  378.     int offset2;
  379.     int skyTexture2;
  380.     int scrollOffset;
  381.  
  382.     extern byte *ylookup[MAXHEIGHT];
  383.     extern int columnofs[MAXWIDTH];
  384.  
  385. #ifdef RANGECHECK
  386.     if(ds_p-drawsegs > MAXDRAWSEGS)
  387.     {
  388.         I_Error("R_DrawPlanes: drawsegs overflow (%i)", ds_p-drawsegs);
  389.     }
  390.     if(lastvisplane-visplanes > MAXVISPLANES)
  391.     {
  392.         I_Error("R_DrawPlanes: visplane overflow (%i)",
  393.             lastvisplane-visplanes);
  394.     }
  395.     if(lastopening-openings > MAXOPENINGS)
  396.     {
  397.         I_Error("R_DrawPlanes: opening overflow (%i)",
  398.             lastopening-openings);
  399.     }
  400. #endif
  401.  
  402.     for(pl = visplanes; pl < lastvisplane; pl++)
  403.     {
  404.         if(pl->minx > pl->maxx)
  405.         {
  406.             continue;
  407.         }
  408.         if(pl->picnum == skyflatnum)
  409.         { // Sky flat
  410.             if(DoubleSky)
  411.             { // Render 2 layers, sky 1 in front
  412.                 offset = Sky1ColumnOffset>>16;
  413.                 skyTexture = texturetranslation[Sky1Texture];
  414.                 offset2 = Sky2ColumnOffset>>16;
  415.                 skyTexture2 = texturetranslation[Sky2Texture];
  416.                 for(x = pl->minx; x <= pl->maxx; x++)
  417.                 {
  418.                     dc_yl = pl->top[x];
  419.                     dc_yh = pl->bottom[x];
  420.                     if(dc_yl <= dc_yh)
  421.                     {
  422.                         count = dc_yh-dc_yl;
  423.                         if(count < 0)
  424.                         {
  425.                             return;
  426.                         }
  427.                         angle = (viewangle+xtoviewangle[x])
  428.                             >>ANGLETOSKYSHIFT;
  429.                         source = R_GetColumn(skyTexture, angle+offset)
  430.                             +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  431.                         source2 = R_GetColumn(skyTexture2, angle+offset2)
  432.                             +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  433.                         dest = ylookup[dc_yl]+columnofs[x];
  434.                         do
  435.                         {
  436.                             if(*source)
  437.                             {
  438.                                 *dest = *source++;
  439.                                 source2++;
  440.                             }
  441.                             else
  442.                             {
  443.                                 *dest = *source2++;
  444.                                 source++;
  445.                             }
  446.                             dest += SCREENWIDTH;
  447.                         } while(count--);
  448.                     }
  449.                 }
  450.                 continue; // Next visplane
  451.             }
  452.             else
  453.             { // Render single layer
  454.                 if(pl->special == 200)
  455.                 { // Use sky 2
  456.                     offset = Sky2ColumnOffset>>16;
  457.                     skyTexture = texturetranslation[Sky2Texture];
  458.                 }
  459.                 else
  460.                 { // Use sky 1
  461.                     offset = Sky1ColumnOffset>>16;
  462.                     skyTexture = texturetranslation[Sky1Texture];
  463.                 }
  464.                 for(x = pl->minx; x <= pl->maxx; x++)
  465.                 {
  466.                     dc_yl = pl->top[x];
  467.                     dc_yh = pl->bottom[x];
  468.                     if(dc_yl <= dc_yh)
  469.                     {
  470.                         count = dc_yh-dc_yl;
  471.                         if(count < 0)
  472.                         {
  473.                             return;
  474.                         }
  475.                         angle = (viewangle+xtoviewangle[x])
  476.                             >>ANGLETOSKYSHIFT;
  477.                         source = R_GetColumn(skyTexture, angle+offset)
  478.                             +SKYTEXTUREMIDSHIFTED+(dc_yl-centery);
  479.                         dest = ylookup[dc_yl]+columnofs[x];
  480.                         do
  481.                         {
  482.                             *dest = *source++;
  483.                             dest += SCREENWIDTH;
  484.                         } while(count--);
  485.                     }
  486.                 }
  487.                 continue; // Next visplane
  488.             }
  489.         }
  490.         // Regular flat
  491.         tempSource = W_CacheLumpNum(firstflat+
  492.             flattranslation[pl->picnum], PU_STATIC);
  493.         scrollOffset = leveltime>>1&63;
  494.         switch(pl->special)
  495.         { // Handle scrolling flats
  496.             case 201: case 202: case 203: // Scroll_North_xxx
  497.                 ds_source = tempSource+((scrollOffset
  498.                     <<(pl->special-201)&63)<<6);
  499.                 break;
  500.             case 204: case 205: case 206: // Scroll_East_xxx
  501.                 ds_source = tempSource+((63-scrollOffset)
  502.                     <<(pl->special-204)&63);
  503.                 break;
  504.             case 207: case 208: case 209: // Scroll_South_xxx
  505.                 ds_source = tempSource+(((63-scrollOffset)
  506.                     <<(pl->special-207)&63)<<6);
  507.                 break;
  508.             case 210: case 211: case 212: // Scroll_West_xxx
  509.                 ds_source = tempSource+(scrollOffset
  510.                     <<(pl->special-210)&63);
  511.                 break;
  512.             case 213: case 214: case 215: // Scroll_NorthWest_xxx
  513.                 ds_source = tempSource+(scrollOffset
  514.                     <<(pl->special-213)&63)+((scrollOffset
  515.                     <<(pl->special-213)&63)<<6);
  516.                 break;
  517.             case 216: case 217: case 218: // Scroll_NorthEast_xxx
  518.                 ds_source = tempSource+((63-scrollOffset)
  519.                     <<(pl->special-216)&63)+((scrollOffset
  520.                     <<(pl->special-216)&63)<<6);
  521.                 break;
  522.             case 219: case 220: case 221: // Scroll_SouthEast_xxx
  523.                 ds_source = tempSource+((63-scrollOffset)
  524.                     <<(pl->special-219)&63)+(((63-scrollOffset)
  525.                     <<(pl->special-219)&63)<<6);
  526.                 break;
  527.             case 222: case 223: case 224: // Scroll_SouthWest_xxx
  528.                 ds_source = tempSource+(scrollOffset
  529.                     <<(pl->special-222)&63)+(((63-scrollOffset)
  530.                     <<(pl->special-222)&63)<<6);
  531.                 break;
  532.             default:
  533.                 ds_source = tempSource;
  534.                 break;
  535.         }
  536.         planeheight = abs(pl->height-viewz);
  537.         light = (pl->lightlevel >> LIGHTSEGSHIFT)+extralight;
  538.         if(light >= LIGHTLEVELS)
  539.         {
  540.             light = LIGHTLEVELS-1;
  541.         }
  542.         if(light < 0)
  543.         {
  544.             light = 0;
  545.         }
  546.         planezlight = zlight[light];
  547.  
  548.         pl->top[pl->maxx+1] = 0xff;
  549.         pl->top[pl->minx-1] = 0xff;
  550.  
  551.         stop = pl->maxx+1;
  552.         for(x = pl->minx; x <= stop; x++)
  553.         {
  554.             R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1],
  555.                 pl->top[x], pl->bottom[x]);
  556.         }
  557.         Z_ChangeTag(tempSource, PU_CACHE);
  558.     }
  559. }
  560.